<?php
/**
 * Created by PhpStorm.
 * User: 9ey
 * Date: 2019/5/18
 * Time: 16:34
 */

namespace App\Repositories\System;

use App\Exceptions\SysException;
use App\Facade\AppContext;
use App\Models\BaseModel;
use App\Models\System\Group;
use App\Models\System\GroupPermission;
use App\Models\System\Role;
use App\Models\System\RolePermission;
use App\Models\System\User;
use App\Repositories\BaseRepository;
use App\Utils\Output;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Throwable;

class RoleRepository extends BaseRepository
{
    function findSystemRole($group_code)
    {
        return Role::query()->where('group_code', '=', $group_code)
            ->where('is_system', '=', 1)
            ->value('id');
    }

    function load($params): Output
    {
        extract($params);
        $query = Role::query();
        if (!empty($group_code)) {
            $query->where('group_code', '=', $group_code);
        }
        return Output::data($query->select('id', 'name')->get());
    }

    function adminPager($params): Output
    {
        extract($params);
        $query = Role::query();
        $query->join('system__groups', 'system__groups.code', '=', 'system__roles.group_code');
        if (!empty($keyword)) {
            $query->where('system__roles.name', 'like', "%$keyword%");
        }
        $query->select(
            'system__roles.id',
            'system__roles.name',
            'system__groups.name as group_name',
            'system__roles.group_code',
            'system__roles.is_system',
            'system__roles.desc'
        );
        return $this->queryToPager($query, $params, 'id');
    }

    function deleteAfter($ids)
    {
        if (User::query()->whereIn('role_id', $ids)->count()) {
            throw new SysException(__('system.role.has_user_cannot_be_deleted'));
        }
    }

    /**
     * 权限
     * @param $id
     * @return Output
     */
    function allPermissions($id): Output
    {
        $role = Role::query()->find($id);
        $groupId = Group::query()->where('code', '=', $role['group_code'])->value('id');
        $permissionCodes = GroupPermission::query()->where('group_id', '=', $groupId)->pluck('permission_code')->toArray();

        $checkedPermissionCodes = RolePermission::query()->where('role_id', '=', $id)->pluck('permission_code')->toArray();
        if (!count($checkedPermissionCodes)) {
            $checkedPermissionCodes = $permissionCodes;
        }
        return (new PermissionRepository())->queryAllPermission($permissionCodes, $checkedPermissionCodes);
    }

    function permissions($id, $group_code): array
    {
        $groupId = Group::query()->where('code', '=', $group_code)->value('id');
        $checkedPermissionCodes = GroupPermission::query()->where('group_id', '=', $groupId)->pluck('permission_code')->toArray();
        $permissionCodes = RolePermission::query()->where('role_id', '=', $id)->pluck('permission_code')->toArray();
        if (!count($permissionCodes)) {
            return $checkedPermissionCodes;
        }
        return (new PermissionRepository())->permissions($permissionCodes, $checkedPermissionCodes);
    }


    /**
     * @param $data
     * @return Output
     */
    function savePermission($data): Output
    {
        try {
            DB::beginTransaction();
            $id = $data['id'];
            $permissionCodes = RolePermission::query()
                ->where('role_id', '=', $id)
                ->pluck('permission_code')
                ->toArray();
            $actions = Arr::get($data, 'actions', []);
            $permissionLogic = new PermissionRepository();
            list($addPermissionIds, $removePermissionIds) = $permissionLogic->permissionDiff($permissionCodes, $actions);
            $dataArray = [];
            foreach ($addPermissionIds as $actionId) {
                $dataArray[] = [
                    'role_id' => $id,
                    'permission_code' => $actionId
                ];
            }
            RolePermission::query()->insert($dataArray);
            RolePermission::query()
                ->where('role_id', '=', $id)
                ->whereIn('permission_code', $removePermissionIds)
                ->delete();
            DB::commit();
            return Output::success();
        } catch (Throwable $exception) {
            DB::rollback();
            return Output::error($exception, __('system.permission.tips.save_err'));
        }
    }

    function groupPermissionUpdate($group_code, $add_permission_ids = [], $remove_permission_ids = [])
    {
        $roleIds = Role::query()->where('group_code', '=', $group_code)->pluck('id');
        if ($roleIds->count()) {
            if (count($add_permission_ids)) {
                $dataArray = [];
                foreach ($roleIds as $roleId) {
                    if (RolePermission::query()->where('role_id', '=', $roleId)->count()) {
                        foreach ($add_permission_ids as $permission_id) {
                            $dataArray[] = [
                                'role_id' => $roleId,
                                'permission_code' => $permission_id
                            ];
                        }
                    }
                }
                RolePermission::query()->insert($dataArray);
            }

            if (count($remove_permission_ids)) {
                RolePermission::query()
                    ->whereIn('role_id', $roleIds)
                    ->whereIn('permission_code', $remove_permission_ids)
                    ->delete();
            }
        }
    }

    function getModel(): BaseModel
    {
        return new Role();
    }
}
